package com.newcapec.modules.iot.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.newcapec.common.exception.RRException;
import com.newcapec.common.utils.iot.DesTools;
import com.newcapec.common.utils.iot.SignUtils;
import com.newcapec.modules.iot.service.IotApiService;
import com.newcapec.modules.iot.utils.IotErrorCode;
import com.newcapec.modules.iot.utils.IotRequest;
import com.newcapec.modules.iot.utils.IotResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 物联网访问接口
 *
 * @author steven
 * @email wangsen127@163.com
 */
@Slf4j
@RestController
@RequestMapping("/iot/api")
public class IotApiController {

    private static final String KEY_SIGN = "sign";

    @Autowired
    private IotApiService iotApiService;
    /**
     * 请求接收
     */
    @PostMapping("/receive")
    public IotResponse receive(HttpServletRequest request, HttpServletResponse response, @RequestBody IotRequest iotRequest) {
        IotResponse iotResponse = new IotResponse();

        //获取物联网请求的业务方法名称
        String method = iotRequest.getMethod();
        iotResponse.setMethod(method);

        //验证签名
        Map map = getHeadersInfo(request);
        log.debug("1.请求头:{}", map);
        String dataStr = map.get("data").toString();
        String requestSign = calResSign(dataStr, iotRequest);
        String signStr = map.get("sign").toString();
        if (!requestSign.equals(signStr)) {
            return IotErrorCode.responseMsg(iotResponse, IotErrorCode.ERROR_SIGN);
        }
        try {
            iotResponse = dealMethod(iotRequest, iotResponse);

            if (StringUtils.isNotBlank(iotRequest.getEncrypt())) {
                String paraStr = (iotResponse.getParam() instanceof String) ? String.valueOf(iotResponse.getParam())
                        : JSON.toJSONString(iotResponse.getParam(), SerializerFeature.WriteMapNullValue);
                paraStr = DesTools.encode(paraStr);
                iotResponse.setParam(paraStr);
            }
            iotResponse.setMethod(method);
            iotResponse.setSignType(iotRequest.getSignType());
            iotResponse.setEncrypt(iotRequest.getEncrypt());
        } catch (Exception e) {
            log.error("error in receive,详细信息:", e);
            iotResponse.setRetcode(IotErrorCode.ERROR_UNKNOW.getErrcode());
            iotResponse.setRetmsg(IotErrorCode.ERROR_UNKNOW.getErrmsg());
        }

        String respnseJsonBody = JSONObject.toJSONString(iotResponse, true);
        log.debug("4.返回待签名字符串:{}", respnseJsonBody);
        String responseSign = calResSign(respnseJsonBody, iotRequest);
        log.debug("5.返回签名:{}", responseSign);
        response.setHeader(KEY_SIGN, responseSign);
        response.setHeader("reqid", map.containsKey("reqid") ? String.valueOf(map.get("reqid")) : "");
        return iotResponse;
    }

    private IotResponse dealMethod(IotRequest iotRequest, IotResponse iotResponse) throws ParseException {
        final String method = iotRequest.getMethod();
        final Object param = iotRequest.getParam();
        final JSONObject paramJson = (JSONObject) JSONObject.toJSON(param);
        switch (method) {
            //时间校对
            case "getISOTime":
                iotResponse = iotApiService.getISOTime(param);
                break;
            //根据学校编号获取学校信息和出入口信息
            case "getBuildingGateList":
                iotResponse = iotApiService.getGateList(iotResponse, paramJson);
                break;
            //设置出入口的机器信息
            case "configBuildingGate":
                iotResponse = iotApiService.configGate(iotResponse, paramJson);
                break;
            //确认覆盖出入口信息
            case "confirmCoverConfig":
                iotResponse = iotApiService.confirmCoverGate(iotResponse, paramJson);
                break;
            //设备扫二维码
            case "getStuInfo":
                iotResponse = iotApiService.scanPersonalQrCode(iotResponse, paramJson);
                break;
            //设备扫人脸
            case "checkRightByStuNo":
                iotResponse = iotApiService.scanFace(iotResponse, paramJson);
                break;
            //提交温度
            case "submitTEMP":
                iotResponse = iotApiService.submitTemperature(iotResponse, paramJson);
                break;
            default:
                return IotErrorCode.responseMsg(iotResponse, IotErrorCode.ERROR_METHOD);
        }
        return iotResponse;
    }

    /**
     * 生成签名
     */
    private String calResSign(String respnseJsonBody, IotRequest iotRequest) {
        String responseSign = null;
        boolean hasSignType = StringUtils.isNotBlank(iotRequest.getSignType());
        // 未指定签名类型,使用默认签名类型HmacSHA1
        if (!hasSignType) {
            try {
                responseSign = SignUtils.getSignatureString(respnseJsonBody, "12345");
            } catch (Exception e) {
                throw new RRException("计算签名错误");
            }
            return responseSign;
        }
        return "";
    }

    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

    /**
     * 人扫码二维码
     */
    @PostMapping("/scanQrCode")
    public IotResponse scanQrCode(@RequestBody Map<String, Object> params) {
        JSONObject paramJson = new JSONObject(params);
        return iotApiService.scanMachineQrCode(paramJson);
    }
}
